"""
@Author : 合肥一元数智教育科技有限公司
@Date :  2025/3/19 14:32
@Description :
"""
import socket
import threading
import time

import wx


class ChatServerFrame(wx.Frame):

    def __init__(self):
        """
            两个文本框    显示聊天记录   输入聊天信息
            四个按钮     加入  离开  清空  发送
        """
        wx.Frame.__init__(self, None, title='群聊服务端', pos=(0, 50), size=(450, 550))
        self.panel = wx.Panel(self)
        self.show_info = wx.TextCtrl(self.panel, style=wx.TE_MULTILINE | wx.TE_READONLY, size=(400, 400), pos=(10, 60))
        self.start_server_btn = wx.Button(self.panel, label='启动服务器', pos=(10, 10), size=(200, 40))
        self.save_message_btn = wx.Button(self.panel, label='保存记录', pos=(220, 10), size=(200, 40))

        # 绑定按钮事件
        self.start_server_btn.Bind(wx.EVT_BUTTON, self.start_server_fn)
        self.save_message_btn.Bind(wx.EVT_BUTTON, self.save_message_fn)

        # socket
        self.server_socket = None
        # 存储客户端socket的列表  群发
        self.all_client_socket = []
        # 服务端的状态
        self.server_state = False

    #  启动服务端
    def start_server_fn(self, event):
        # 判定服务器状态  避免重复启动
        if not self.server_state:
            self.show_info.AppendText('启动服务器,等待客户端的连接...\n')
            self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.server_socket.bind(('192.168.1.49', 9999))
            self.server_socket.listen(5)
            # 改变服务端状态
            self.server_state = True
            # 等待客户端连接   窗口会未响应   函数调用不能结束  阻塞
            # client_socket, client_address = self.server_socket.accept()
            # 通过新的线程监听客户端的连接   解决窗口未响应
            threading.Thread(target=self.accept_all_client).start()

    #  监听用户的连接任务
    def accept_all_client(self):
        while self.server_state:
            client_socket, client_address = self.server_socket.accept()
            # 保存连接的客户端socket
            self.all_client_socket.append(client_socket)
            notice_message = f'【系统通知】{client_address[0]}:{client_address[1]} 用户上线了...\n'
            self.show_info.AppendText(notice_message)
            # 群发客户端上线通知
            for one_socket in self.all_client_socket:
                one_socket.send(notice_message.encode('utf-8'))
            # 创建一个新的线程  执行客户端消息的接收
            threading.Thread(target=self.handle_all_client, args=(client_socket, client_address)).start()

    # 监听客户端消息
    def handle_all_client(self, client_socket, client_address):
        try:
            while self.server_state:
                client_message = client_socket.recv(1024).decode('utf-8')
                return_message = f'【{client_address[0]}:{client_address[1]}】: {client_message}\n'
                self.show_info.AppendText(return_message)
                # 遍历群发
                for one_socket in self.all_client_socket:
                    one_socket.send(return_message.encode('utf-8'))
        except ConnectionResetError:
            # 剔除下线的用户
            self.all_client_socket.remove(client_socket)
            # 群发离线信息
            notice_message = f'【系统通知】{client_address[0]}:{client_address[1]} 用户下线了...\n'
            self.show_info.AppendText(notice_message)
            for one_socket in self.all_client_socket:
                one_socket.send(notice_message.encode('utf-8'))

    # 保存聊天记录     将聊天的信息写入本地文件  做好每次保存信息前先记录一次保存时间
    def save_message_fn(self, event):
        if self.server_state:
            with open('chat_log.txt', 'a', encoding='utf-8') as f:
                current_time = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())
                f.write(f'*********************{current_time}**********************\n')
                f.write(self.show_info.GetValue())


if __name__ == '__main__':
    app = wx.App()
    chat_server_frame = ChatServerFrame()
    chat_server_frame.Show()
    app.MainLoop()
